#include "interpolator.h"
#include "g_code.h"
#include "sys.h"
#include "tcp_interface.h"
#ifdef __linux__
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <time.h>
#include <stdlib.h>
#elif _WIN32
#endif
#define SERV_PORT 	11860                  //服务器端口
#define SERV_ADDR 	"0.0.0.0"		  //服务器ip
#define BACKLOG 	100    				  //服务器最多可以监听的客户端数量(最多排队数量)
char tcp_recv_buf[100];
char tcp_send_buf[100];
int client_num = 0;   //连接的客户端计数
int system_busy = 0;
#define pS_UINT8(x) (*(unsigned char*)(x))
#define pS_UINT16(x) ((cx_uint16_t)pS_UINT8(x)+(((cx_uint16_t)(pS_UINT8(x+1)))<<8))
// DDA_Interpolator_t MainInterpolator;
g_code_param_t g_code_param_ret;
int sockfd = -1;  	//定义socket网络文件描述符


#ifdef __linux__
typedef struct Timer {
    pthread_mutex_t mutex;
    pthread_cond_t cond;
	pthread_t thread;
    int interval; // 定时器间隔，毫秒
    int running; // 定时器是否运行
} Timer;
 Timer timer;
pthread_t Server_thread;
struct sockaddr_in servaddr={0};  //服务器sockaddr_in定义成ipv4类型的服务器ip结构体（ipv6是sockaddr_inv6）
struct sockaddr_in cliaddr={0};   //客户端sockaddr_in
socklen_t address_len = 0;         //客户端长度
int clifd = -1;   	//定义accept网络文件描述符
void timer_init(Timer *timer, int interval) {
    pthread_mutex_init(&timer->mutex, NULL);
    pthread_cond_init(&timer->cond, NULL);
    timer->interval = interval;
    timer->running = 0;
}
 
void* timer_thread(void *arg) {
    Timer *timer = (Timer *)arg;
    struct timespec abstime;
    while (timer->running) {
        pthread_mutex_lock(&timer->mutex);
        clock_gettime(CLOCK_REALTIME, &abstime);
        abstime.tv_sec += timer->interval / 1000;
        abstime.tv_nsec += (timer->interval % 1000) * 1000000;
        int rc = pthread_cond_timedwait(&timer->cond, &timer->mutex, &abstime);
        if (rc == 0) {
            // 定时器触发，执行任务
            interpolator_Handler();
        }
        pthread_mutex_unlock(&timer->mutex);
    }
    return NULL;
}

void timer_start(Timer *timer) {
    timer->running = 1;
    pthread_create(&timer->thread, NULL, &timer_thread, (void *)timer);
}
 
void timer_stop(Timer *timer) {
    timer->running = 0;
    pthread_cond_broadcast(&timer->cond); // 唤醒等待的线程
    pthread_join(timer->thread, NULL); // 等待定时器线程结束
}
 
void *server(void *args)
{
	int ret = -1;
	while(1)
	{
		//4.使用accept函数阻塞等待客户端连接，注意：会阻塞！！！
		//函数原型：int accept(int socket, struct sockaddr *restrict address,socklen_t *restrict address_len);
		address_len = sizeof(struct sockaddr);  //给client_len赋值
		clifd = accept(sockfd, (struct sockaddr *)&cliaddr,&address_len);     //此时会阻塞在这监听客户端连接
		if(clifd < 0)
		{
			printf("faild in accepting\n");
		}
        printf("accept:%d\n",clifd);
        printf("Client:%d.%d.%d.%d:%d\n",cliaddr.sin_addr.s_addr & 0x000f,cliaddr.sin_addr.s_addr & 0x00f0 >> 8,cliaddr.sin_addr.s_addr & 0x0f00 >> 16,cliaddr.sin_addr.s_addr & 0xf000 >> 24,cliaddr.sin_port);
		// cout<<"listen连接客户端成功,clifd ="<<clifd<<endl;
		// cout<<"客户端端口号port= "<<ntohs(cliaddr.sin_port)<<endl;
		// cout<<"客户端ip= "<<inet_ntoa(cliaddr.sin_addr)<<endl;
		
		//在收到客户端连接成功后创建一个新的线程，在线程里进行数据收发
		// client_num++;    //当前服务的客户端数量加1
		while(1)
        {	
            ret = recv(clifd, tcp_recv_buf, sizeof(tcp_recv_buf), 0);   //接收客户端发送来的数据，注意此处使用的网络描述符是clifd
            if(ret < 1)
            {
                printf("disconnected\n");
                close(clifd);      //关闭accept文件描述符clifd
                break;
            }
            // printf("recieved:%s\n",tcp_recv_buf);
            switch (CONVERT_PACKET(tcp_recv_buf)->type)
            {
            case TRANSACTION_TYPE_ACK:
                break;
            case TRANSACTION_TYPE_G_CODE:
                tcp_recv_buf[ret] = '\0';
                printf("G_CODE:%s\n",CONVERT_PACKET(tcp_recv_buf)->data);
                // send(clifd,tcp_recv_buf,ret,0);
                g_code_get_param(CONVERT_PACKET(tcp_recv_buf)->data,&g_code_param_ret);
                CONVERT_PACKET(tcp_send_buf)->lenght = 2;
                CONVERT_PACKET(tcp_recv_buf)->type = TRANSACTION_TYPE_ACK;
                ret = send(clifd,tcp_send_buf,CONVERT_PACKET(tcp_send_buf)->lenght,0);
                break;
            case TRANSACTION_TYPE_CONTROL_MAINSHARFT_SPEED:
                system_feed_speed = pS_UINT16(CONVERT_PACKET(tcp_recv_buf)->data)/100.0f;
                printf("feed:%f\n",system_feed_speed);
                ret = send(clifd,tcp_send_buf,CONVERT_PACKET(tcp_send_buf)->lenght,0);
                break;
            case TRANSACTION_TYPE_CONTROL_MAINSHARFT_SWITCH:
                break;
            case TRANSACTION_TYPE_CONTROL_COOLING_SWITCH:
                break;
            case TRANSACTION_TYPE_CONTROL_FEED_SPEED:
                break;
            case TRANSACTION_TYPE_CONTROL_FEED_RATE:
                break;
            
            default:
                break;
            }
            // ret = send(clifd, send_buf, strlen(send_buf), 0);
            // memset(send_buf,0,sizeof(send_buf));   //清空接收缓存区
        }
	}
}
#elif _WIN32

#endif
int main(int argc,char **argv)
{
	int ret = -1;
	
	timer_init(&timer,5);
	timer_start(&timer);
	printf("deamon OK\n");
	//1.首先使用socket函数创建网络文件描述符（类似于文件IO中的open函数）
    //函数原型：int socket(int domain, int type, int protocol);   
	
	sockfd = socket(AF_INET, SOCK_STREAM, 0);   //ipv4,TCP,系统自动选择protocol
	if(sockfd < 0)
	{
		printf("faild in creat socket\n");
	}
	printf("socket:%d\n",sockfd);

	//注意：由TCP套接字状态TIME_WAIT引起在结束本次会话后close立刻开启下次会话会Bind失败。
	//该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后，套接字被删除，该地址才能被重新绑定而不出问题。
	//因此下面两句话的加入可以解决这个问题
	int on = 1;
	ret = setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );

	//2.使用bind函数绑定socket文件描述符和相关参数
	//函数原型：int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); 
	servaddr.sin_family = AF_INET;             //定义servaddr的domain地址族为ipv4
	servaddr.sin_port = htons(SERV_PORT);      //定义servaddr的portnum为SERV_PORT(8010),host to net short
	servaddr.sin_addr.s_addr = inet_addr(SERV_ADDR);  //定义servaddr的address为SERV_ADDR(192.168.1.23)  person----->u32
	//servaddr.sin_addr.s_addr = INADDR_ANY;  //监听该电脑的所有IP
	memset(servaddr.sin_zero,0,sizeof(servaddr.sin_zero));   //设置servaddr的sin_zero区域为0
	ret = bind(sockfd, (const struct sockaddr *)&servaddr,sizeof(servaddr));   //使用bind函数绑定socket文件描述符和相关参数
	if(ret < 0)
	{
		printf("fail in binding socket\n");
	}
	printf("bind finished\n");
    //3.使用listen函数进行接收监听(监听当前设置的ip地址下的端口号port)
	//函数原型：int listen(int socket, int backlog);
	ret = listen(sockfd, BACKLOG);     //sockfd,等待列表，最多可以排队排BACKLOG(100)个
	if(ret < 0)
	{
		printf("faild in listening\n");
	}
	printf("listening on %s:%d...\n",SERV_ADDR, SERV_PORT);
	pthread_create(&Server_thread,NULL,server,NULL);
	while(1);
	close(sockfd);     //关闭socket文件描述符

	return 0;
}